/*! \file $Id: Write_Logger.hpp 28822 2013-09-06 09:26:49Z skh $
 * \author skh
 * \brief Write Logger
 */

#ifndef WRITE_LOGGER_HPP
#define WRITE_LOGGER_HPP
#include "logger/phlogger.h"
#include <stdarg.h>
#include <sstream>
#include <iostream>
#include "get_thread_id.h"

#ifndef WIN32
#define  __CLRCALL_OR_CDECL
#endif

namespace
{
    struct  WriteLogHelper
    {
        WriteLogHelper(int flag):flag(flag){}
        template <class T>
        WriteLogHelper& operator<<(const T&t)
        {
            oss << t;
            return *this;
        }
        WriteLogHelper& operator<<(WriteLogHelper& (__CLRCALL_OR_CDECL *_Pfn)(WriteLogHelper&))
        {
            return ((*_Pfn)(*this));
        }
        ~WriteLogHelper()
        {
            WriteLog(flag,"%s",oss.str().c_str());
        }
        int flag;
        std::ostringstream oss;
    };
}
namespace std
{
    inline 
    WriteLogHelper& __CLRCALL_OR_CDECL endl(WriteLogHelper& _Ostr)
    {	// insert newline and flush stream
        _Ostr.oss.put(_Ostr.oss.widen('\n'));
        _Ostr.oss.flush();
        return (_Ostr);
    }
}

#define LOG_FILE 		(strrchr(__FILE__, '\\') == NULL ? __FILE__ : strrchr(__FILE__, '\\') + 1)
#define LOG_FUNCTION 	__FUNCTION__

#define LOG_LINE     	LOG_LINE0(__LINE__)
#define LOG_LINE0(x) 	LOG_LINE1(x)
#define LOG_LINE1(x) 	#x

#ifdef DEBUG
  #define LOG_END   " [at " << LOG_FUNCTION << " (" << LOG_FILE << ":" LOG_LINE ")]"
#else
  #define LOG_END   ""
#endif

#define WRITE_LOG_DEBUG WriteLogHelper(LOG_DEBUG)
#define WRITE_LOG_INFO  WriteLogHelper(LOG_INFO)
#define WRITE_LOG_WARN  WriteLogHelper(LOG_WARNING)
#define WRITE_LOG_ERROR WriteLogHelper(LOG_ERROR)

//test
#if defined(DEBUG) || defined(_DEBUG)
  #define WRITE_LOG_INFO_TEST   (WRITE_LOG_INFO  << "[test] thread:" << gettid2() << " func:" << LOG_FUNCTION << " [at (" << LOG_FILE << ":" LOG_LINE ")]")
  #define WRITE_LOG_WARN_TEST   (WRITE_LOG_WARN  << "[test] thread:" << gettid2() << " func:" << LOG_FUNCTION << " [at (" << LOG_FILE << ":" LOG_LINE ")]")
  #define WRITE_LOG_DEBUG_TEST  (WRITE_LOG_DEBUG << "[test] thread:" << gettid2() << " func:" << LOG_FUNCTION << " [at (" << LOG_FILE << ":" LOG_LINE ")]")
  #define WRITE_LOG_ERROR_TEST  (WRITE_LOG_ERROR << "[test] thread:" << gettid2() << " func:" << LOG_FUNCTION << " [at (" << LOG_FILE << ":" LOG_LINE ")]")
  #define OUTPUT_LOG_TEST       (WRITE_LOG_INFO)
#else
  #define WRITE_LOG_INFO_TEST   (std::cout)
  #define WRITE_LOG_WARN_TEST   (std::cout)
  #define WRITE_LOG_DEBUG_TEST  (std::cout)
  #define WRITE_LOG_ERROR_TEST  (std::cout)
  #define OUTPUT_LOG_TEST       (std::cout)
#endif

//#define WRITE_LOG_INFO_THREAD   (WRITE_LOG_INFO << "\n>>> [test] thread:" << gettid2() << " func:" << LOG_FUNCTION << " [at (" << LOG_FILE << ":" LOG_LINE ")]\n")

#endif
